package cn.com.hatech.cdkey.common.utils;

import org.thymeleaf.util.StringUtils;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESOperator {

    /**
     * 加密用的Key 可以用26个字母和数字组成 此处使用AES-128-CBC加密模式，key需要为16位。
     */
    public static final String tenantLicenseKey = "smkldospdosldaaa";
    /**
     * 租户相关限制信息加密key
     */
    public static final String tenantInfoKey = "smklosldaaadospd";

    /**
     * 偏移量
     */
    private String ivParameter = "1016449182158477";


    private static AESOperator instance = null;

    private AESOperator() {

    }

    public static AESOperator getInstance() {
        if (instance == null) {
            instance = new AESOperator();
        }
        return instance;
    }

    public static String Encrypt(String encData, String secretKey, String vector) throws Exception {

        if (secretKey == null) {
            return null;
        }
        if (secretKey.length() != 16) {
            return null;
        }
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] raw = secretKey.getBytes();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        IvParameterSpec iv = new IvParameterSpec(vector.getBytes());// 使用CBC模式，需要一个向量iv，可增加加密算法的强度
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(encData.getBytes("utf-8"));
        return new BASE64Encoder().encode(encrypted);// 此处使用BASE64做转码。
    }


    /**
     * 加密
     *
     * @param sSrc
     * @param sKey
     * @return
     * @throws Exception
     */
    public String encrypt(String sSrc, String sKey) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] raw = sKey.getBytes();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());// 使用CBC模式，需要一个向量iv，可增加加密算法的强度
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
        return replace(new BASE64Encoder().encode(encrypted));// 此处使用BASE64做转码。
    }

    /**
     * 解密
     *
     * @param sSrc
     * @param sKey
     * @return
     */
    public String decrypt(String sSrc, String sKey) {
        try {
            byte[] raw = sKey.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);// 先用base64解密
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "utf-8");
            return originalString;
        } catch (Exception ex) {
            return null;
        }
    }

    public String decrypt(String sSrc, String key, String ivs) throws Exception {
        try {
            byte[] raw = key.getBytes("ASCII");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec(ivs.getBytes());
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);// 先用base64解密
            byte[] original = cipher.doFinal(encrypted1);
            String originalString = new String(original, "utf-8");
            return originalString;
        } catch (Exception ex) {
            return null;
        }
    }

    public static String encodeBytes(byte[] bytes) {
        StringBuffer strBuf = new StringBuffer();

        for (int i = 0; i < bytes.length; i++) {
            strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ((int) 'a')));
            strBuf.append((char) (((bytes[i]) & 0xF) + ((int) 'a')));
        }

        return strBuf.toString();
    }

    /**
     * 去除 换行符、制表符
     *
     * @param str
     * @return
     */
    public String replace(String str) {
        if (!StringUtils.isEmpty(str)) {
            return str.replaceAll("\r|\n", "");
        }
        return str;
    }

    public static void main(String[] args) throws Exception {
        // 需要加密的字串
        String cSrc = "{\"username\":\"zh\",\"userCount\":40,\"businessCount\":25,\"assetsCount\":30,\"daysUsed\":30,\"confusion\":\"shylfi2rt2caa1iee\",\"menuCodes\":[\"bcms_1\",\"bcms_2\",\"bcms_4\",\"bcms_6\",\"bcms_7\",\"bcms_11\",\"bcms_12\",\"bcms_14\",\"bcms_17\",\"bcms_18\"],\"description\":\"北京同创永益科技发展有限公司（以下简称“同创永益”）是面向未来的组织韧性服务提供商，专注于提供业务连续性、IT韧性和灾难恢复相关产品、解决方案及服务的国家级高新技术企业。公司在业务连续性、灾难恢复、IT运营管理、IT容量韧性、3D可视化、风险与应急管理等专业领域为企业级客户提供完整的解决方案，并通过与众多优秀合作伙伴搭建完善的产业生态体系，共同为企业级客户组织韧性保驾护航。作为该领域的领军企业，公司凭借领先的技术创新实力、强大的本地服务能力和个性化交付能力得到了资本市场的认可。2019年8月，同创永益完成近亿元B轮融资，步入发展的快车道。  目前，同创永益已经成功服务于金融、能源、制造、电信等行业的众多头部客户，累计近百家全球及中国500强企业，其中包括国家电网、南方电网、中国移动、中石化、中国海油、万达集团、万华化学、中国银联、上海黄金交易所、江苏省农信、湖北省农信、武汉农村商业银行、南京银行、太平保险集团等。  同创永益总部设在北京，在上海、深圳、武汉、南京、苏州、成都、郑州等地均设有分公司和办事处，构建了包括高端咨询服务、软件现场交付服务、400售后服务于一体的完整服务体系，打造行业最佳落地实践和客户体验。目前公司人员80%以上为研发和咨询团队，核心成员均是来自于IBM、EMC、华为、工商银行等具备多年中大型企业客户服务经验的专家。  公司秉承开放共赢的理念，不断自主研发创新，期望在业务连续性、IT韧性和灾难恢复领域成为最具影响力的领导者，成为客户业务连续性的最后一道防线，并携手合作伙伴，在支撑客户关键业务成长的同时，为客户持续创造新的业务价值，围绕客户需求和产业发展，共创美好数字化未来。\"}";
        // 加密
        String enString = AESOperator.getInstance().encrypt(cSrc, tenantLicenseKey);
        System.out.println("加密后的字串是：" + enString);

        // 解密
        String DeString = AESOperator.getInstance().decrypt(enString, tenantLicenseKey);
        System.out.println("解密后的字串是：" + DeString);
    }

}
